package com.example.gmranqi.common.conver;


import com.alibaba.fastjson.JSON;
import com.example.gmranqi.common.conver.annitation.ConverMapper;
import com.example.gmranqi.common.conver.annitation.DefaultVal;
import com.example.gmranqi.common.conver.annitation.EnumDesc;
import com.example.gmranqi.common.conver.annitation.Precision;
import com.example.gmranqi.common.enums.EnumInterface;
import com.example.gmranqi.utils.DateUtils;
import com.example.gmranqi.utils.EnumUtils;
import com.example.gmranqi.utils.ReflectionUtils;
import com.example.gmranqi.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;

public class EntityConver {
	private static final Logger logger = LoggerFactory.getLogger(EntityConver.class);

	/**
	 * 对象转换，默认使用源对象注解
	 * 
	 * @param source
	 *            源对象
	 * @param targetClass
	 *            目标对象类型
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, Class<E> targetClass) {
		return conver(source, targetClass, ConverType.SOURCE, null);
	}

	/**
	 * 对象转换，默认使用源对象注解
	 * 
	 * @param source
	 *            源对象
	 * @param target
	 *            目标对象
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, E target) {
		return conver(source, target, ConverType.SOURCE, null);
	}

	/**
	 * 对象转换，默认使用源对象注解
	 * 
	 * @param source
	 *            源对象
	 * @param targetClass
	 *            目标对象类型
	 * @param customConver
	 *            转换回调方法，实现部分自定义转换逻辑
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, Class<E> targetClass, CustomConver customConver) {
		return conver(source, targetClass, ConverType.SOURCE, customConver);
	}

	/**
	 * 对象转换
	 * 
	 * @param source
	 *            源对象
	 * @param targetClass
	 *            目标对象类型
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, Class<E> targetClass, ConverType converType) {
		return conver(source, targetClass, converType, null);
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @return 目标对象集合
	 */
	public static <E> List<E> converList(List<?> list, Class<E> targetClass) {
		return converList(list, targetClass, ConverType.SOURCE, null);
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @return 目标对象集合
	 */
	public static <E> List<E> converList(List<?> list, Class<E> targetClass, ConverType converType) {
		return converList(list, targetClass, converType, null);
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @param customConver
	 *            转换回调方法，实现部分自定义转换逻辑
	 * @return 目标对象集合
	 */
	public static <E> List<E> converList(List<?> list, Class<E> targetClass, CustomConver customConver) {
		return converList(list, targetClass, ConverType.SOURCE, customConver);
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @param function
	 *            转换目标对象额外处理逻辑
	 * @return 目标对象集合
	 */
	public static <E> List<E> converArray(List<?> list, Class<E> targetClass, Function<E, E> function) {
		return converArray(list, targetClass, ConverType.SOURCE, function);
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @param customConver
	 *            转换回调方法，实现部分自定义转换逻辑
	 * @return 目标对象集合
	 */
	public static <E> List<E> converList(List<?> list, Class<E> targetClass, ConverType converType, CustomConver customConver) {
		if (list == null || list.isEmpty())
			return null;
		try {
			List<E> data = new ArrayList<>(list.size());

			Class<?> loopClass = null;
			Class<?> converClass = null;
			Class<?> objectClass = list.get(0).getClass();

			switch (converType) {
			case SOURCE:
				loopClass = objectClass;
				converClass = targetClass;
				break;
			case TARGET:
				loopClass = targetClass;
				converClass = objectClass;
				break;
			}

			List<Field> loopClassFields = new ArrayList<>();
			for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
				Field[] fields = clazz.getDeclaredFields();
				for (Field field : fields) {
					if (!Modifier.isFinal(field.getModifiers())) {
						field.setAccessible(true);
						loopClassFields.add(field);
					}
				}
			}

			Map<String, Field> converClassFields = new HashMap<>();
			for (Class<?> clazz = converClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
				Field[] fields = clazz.getDeclaredFields();
				for (Field field : fields) {
					if (!Modifier.isFinal(field.getModifiers())) {
						field.setAccessible(true);
						converClassFields.put(field.getName(), field);
					}
				}
			}

			for (Object o : list) {
				E e = conver(o, targetClass, converType, customConver, loopClass, converClass, loopClassFields, converClassFields);
				if (e != null)
					data.add(e);
			}
			return data;
		} catch (Exception ex) {
			logger.error("Entity converList error, list={}, targetClass={}, converType={}", JSON.toJSONString(list), targetClass, converType, ex);
		}
		return null;
	}

	/**
	 * 批量对象转换，默认使用源对象注解
	 * 
	 * @param list
	 *            源对象集合
	 * @param targetClass
	 *            目标对象类型
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @param function
	 *            转换目标对象额外处理逻辑
	 * @return 目标对象集合
	 */
	public static <E> List<E> converArray(List<?> list, Class<E> targetClass, ConverType converType, Function<E, E> function) {
		if (list == null || list.isEmpty())
			return null;
		try {
			List<E> data = new ArrayList<>(list.size());

			Class<?> loopClass = null;
			Class<?> converClass = null;
			Class<?> objectClass = list.get(0).getClass();

			switch (converType) {
			case SOURCE:
				loopClass = objectClass;
				converClass = targetClass;
				break;
			case TARGET:
				loopClass = targetClass;
				converClass = objectClass;
				break;
			}

			List<Field> loopClassFields = new ArrayList<>();
			for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
				Field[] fields = clazz.getDeclaredFields();
				for (Field field : fields) {
					if (!Modifier.isFinal(field.getModifiers())) {
						field.setAccessible(true);
						loopClassFields.add(field);
					}
				}
			}

			Map<String, Field> converClassFields = new HashMap<>();
			for (Class<?> clazz = converClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
				Field[] fields = clazz.getDeclaredFields();
				for (Field field : fields) {
					if (!Modifier.isFinal(field.getModifiers())) {
						field.setAccessible(true);
						converClassFields.put(field.getName(), field);
					}
				}
			}

			for (Object o : list) {
				E e = conver(o, targetClass, converType, null, loopClass, converClass, loopClassFields, converClassFields);
				if (e != null) {
					if (function != null) {
						e = function.apply(e);
					}
					if (e != null)
						data.add(e);
				}
			}
			return data;
		} catch (Exception ex) {
			logger.error("Entity converList error, list={}, targetClass={}, converType={}", JSON.toJSONString(list), targetClass, converType, ex);
		}
		return null;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static <E> E conver(Object o, Class<E> targetClass, ConverType converType, CustomConver customConver, Class<?> loopClass, Class<?> converClass,
			List<Field> loopClassFields, Map<String, Field> converClassFields) {
		try {
			E e = targetClass.newInstance();

			for (Field field : loopClassFields) {
				try {
					Object val = null;
					Field setField = null;
					ConverMapper mapper = field.getAnnotation(ConverMapper.class);
					Precision precision = field.getAnnotation(Precision.class);
					String targetFielde = null;
					if (mapper != null) {
						String converClassName = converClass.getName();
						if (mapper.targetClass().length == 0) {
							targetFielde = mapper.targetFielde()[0];
						} else {
							for (int i = 0; i < mapper.targetClass().length; i++) {
								String mapperClass = mapper.targetClass()[i];

								if (mapperClass.equals(converClassName)) {
									targetFielde = mapper.targetFielde()[i];
									break;
								}
							}
						}
					}

					String fieldName = null;
					if (targetFielde != null && !targetFielde.isEmpty()) {
						fieldName = targetFielde;
					} else {
						fieldName = field.getName();
					}

					if (converType == ConverType.SOURCE) {
						val = field.get(o);
						setField = converClassFields.get(fieldName);
					} else if (converType == ConverType.TARGET) {
						Field getField = converClassFields.get(fieldName);

						if (getField != null) {
							val = getField.get(o);
						}

						setField = field;
					}

					enumDescConver(o, e, field);

					if (setField == null)
						continue;

					if (customConver != null)
						val = customConver.handler(val, setField);

					if (val == null) {
						DefaultVal defaultVal = field.getAnnotation(DefaultVal.class);
						if (defaultVal != null)
							val = defaultVal.val();
						else
							continue;
					} else if (precision != null) {
						int movePoint = precision.movePoint();
						int scale = precision.scale();
						RoundingMode roundingMode = precision.roundingMode();

						BigDecimal bigDecimal = new BigDecimal(val.toString());
						bigDecimal = bigDecimal.movePointRight(movePoint).setScale(scale, roundingMode);

						if (setField.getType().equals(Short.class)) {
							val = bigDecimal.shortValue();
						} else if (setField.getType().equals(Integer.class)) {
							val = bigDecimal.intValue();
						} else if (setField.getType().equals(Long.class)) {
							val = bigDecimal.longValue();
						} else if (setField.getType().equals(Float.class)) {
							val = bigDecimal.floatValue();
						} else if (setField.getType().equals(Double.class)) {
							val = bigDecimal.doubleValue();
						} else if (setField.getType().equals(String.class)) {
							val = bigDecimal.toString();
						} else {
							val = bigDecimal;
						}
					}

					// 类型转换
					if (Collection.class.isAssignableFrom(setField.getType())) {// 集合转换
						Type genericType = ((ParameterizedType) setField.getGenericType()).getActualTypeArguments()[0];
						if (genericType instanceof WildcardType) {
							WildcardType wildcardType = (WildcardType) genericType;
							Type[] bounds = wildcardType.getLowerBounds();
							if (bounds.length == 0) {
								bounds = wildcardType.getUpperBounds();
							}
							genericType = bounds[0];
						}
						Class setFieldGenericClass = (Class) genericType;
						if (Collection.class.isAssignableFrom(val.getClass())) {
							Collection values = ((Collection) val);
							Collection setFieldCollection = null;

							if (Set.class.isAssignableFrom(setField.getType()))
								setFieldCollection = new HashSet<>();
							else if (List.class.isAssignableFrom(setField.getType()))
								setFieldCollection = new ArrayList<>();

							for (Object obj : values) {
								if (obj == null)
									continue;
								if (setFieldGenericClass.equals(String.class)) {
									obj = obj.toString();
								} else if (setFieldGenericClass.equals(Short.class)) {
									obj = Short.parseShort(obj.toString());
								} else if (setFieldGenericClass.equals(Integer.class)) {
									obj = Integer.parseInt(obj.toString());
								} else if (setFieldGenericClass.equals(Long.class)) {
									obj = Long.parseLong(obj.toString());
								} else if (setFieldGenericClass.equals(Float.class)) {
									obj = Float.parseFloat(obj.toString());
								} else if (setFieldGenericClass.equals(Double.class)) {
									obj = Double.parseDouble(obj.toString());
								} else if (setFieldGenericClass.isEnum()) {
									if (obj.getClass().equals(String.class)) {
										obj = Enum.valueOf(setFieldGenericClass, obj.toString());
									}
								} else if (!setFieldGenericClass.equals(obj.getClass())) {// 复合对象转换
									obj = conver(obj, setFieldGenericClass, converType);
								}
								setFieldCollection.add(obj);
							}
							if (!setFieldCollection.isEmpty())
								val = setFieldCollection;
						} else if (val.getClass().equals(String.class)) {
							val = JSON.parseArray(val.toString(), setFieldGenericClass);
						}
					} else if (Map.class.isAssignableFrom(setField.getType()) && Map.class.isAssignableFrom(val.getClass())) {
						// 不处理
					} else if (!setField.getType().equals(val.getClass())) {
						if (setField.getType().equals(Date.class)) {// 日期转换
							if (val.getClass().equals(Long.class))
								val = new Date((Long) val);
							else if (val.getClass().equals(String.class))
								val = DateUtils.convertDateString(val.toString());
						} else if (setField.getType().equals(Long.class)) {
							if (val.getClass().equals(Date.class))// 日期转换
								val = ((Date) val).getTime();
							else if (val.getClass().equals(String.class)) {
								if (DateUtils.validateLongDateFormat(val.toString()) || DateUtils.validateUnsignedDateFormat(val.toString())
										|| DateUtils.validateShortDateFormat(val.toString()))// 日期转换
									val = DateUtils.convertDateStringToMillisecond(val.toString());
								else
									val = Long.parseLong(val.toString());
							} else if (val.getClass().equals(Integer.class)) {
								val = ((Integer) val).longValue();
							}
						} else if (setField.getType().equals(String.class)) {
							if (val.getClass().equals(Date.class))// 日期转换
								val = DateUtils.convertToLongDateString((Date) val);
							else if (!val.getClass().isPrimitive())
								val = JSON.toJSONString(val);
							else
								val = val.toString();
						} else if (setField.getType().equals(Integer.class)) {
							if (val.getClass().equals(String.class)) {
								val = Integer.parseInt(val.toString());
							} else if (val.getClass().equals(Long.class)) {
								val = ((Long) val).intValue();
							} else if (val.getClass().equals(Byte.class)) {
								val = ((Byte) val).intValue();
							}

						} else if (setField.getType().equals(Double.class)) {
							if (val.getClass().equals(String.class)) {
								val = Double.parseDouble(val.toString());
							}
						} else if (setField.getType().equals(Boolean.class)) {
							if (val.getClass().equals(String.class)) {
								val = Boolean.parseBoolean(val.toString());
							}
						} else if (setField.getType().equals(Float.class)) {
							if (val.getClass().equals(String.class)) {
								val = Float.parseFloat(val.toString());
							}
						} else if (setField.getType().equals(Short.class)) {
							if (val.getClass().equals(String.class)) {
								val = Short.parseShort(val.toString());
							}
						} else if (setField.getType().equals(Byte.class)) {
							if (val.getClass().equals(String.class)) {
								val = Byte.parseByte(val.toString());
							} else if (val.getClass().equals(Integer.class)) {
								val = ((Integer) val).byteValue();
							}
						} else if (setField.getType().isEnum()) {
							if (val.getClass().equals(String.class)) {
								val = Enum.valueOf((Class) setField.getType(), val.toString());
							}
						} else if (setField.getType().equals(BigDecimal.class)) {
							val = new BigDecimal(val.toString());
						} else if (setField.getType().equals(StringBuilder.class)) {
							val = new StringBuilder(val.toString());
						} else if (!setField.getType().isPrimitive()) {// 复合对象转换
							if (val.getClass().equals(String.class))
								val = JSON.parseObject(val.toString(), setField.getType());
							else
								val = conver(val, setField.getType(), converType);
						}
					}

					setField.set(e, val);

				} catch (Exception ex) {
					logger.error("Entity conver error, object={}, targetClass={}, converType={}, loopClass={}", o, targetClass, converType, loopClass, ex);
				}
			}

			return e;
		} catch (Exception ex) {
			logger.error("Entity conver error, object={}, targetClass={}, converType={}", o, targetClass, converType, ex);
		}
		return null;
	}

	/**
	 * 对象转换，默认使用源对象注解
	 * 
	 * @param source
	 *            源对象
	 * @param targetClass
	 *            目标对象类型
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @param customConver
	 *            转换回调方法，实现部分自定义转换逻辑
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, Class<E> targetClass, ConverType converType, CustomConver customConver) {
		if (targetClass == null)
			return null;

		try {
			E target = targetClass.newInstance();
			return conver(source, target, converType, customConver);
		} catch (Exception e) {
			logger.error("Entity conver error, source={}, targetClass={}, converType={}", JSON.toJSONString(source), targetClass, converType, e);
		}

		return null;
	}

	/**
	 * 对象转换，默认使用源对象注解
	 * 
	 * @param source
	 *            源对象
	 * @param target
	 *            目标对象
	 * @param converType
	 *            注解生效对象，原对象或目标对象
	 * @param customConver
	 *            转换回调方法，实现部分自定义转换逻辑
	 * @return 目标对象
	 */
	public static <E> E conver(Object source, E target, ConverType converType, CustomConver customConver) {
		if (source == null || target == null || converType == null) {
			return null;
		}
		try {
			Class<?> loopClass = null;
			Class<?> converClass = null;
			Class<?> objectClass = source.getClass();
			Class<?> targetClass = target.getClass();

			switch (converType) {
			case SOURCE:
				loopClass = objectClass;
				converClass = targetClass;
				break;
			case TARGET:
				loopClass = targetClass;
				converClass = objectClass;
				break;
			}

			for (Class<?> clazz = loopClass; clazz != Object.class; clazz = clazz.getSuperclass()) {
				try {
					Field[] fields = clazz.getDeclaredFields();

					if (fields == null)
						continue;

					for (Field field : fields) {
						if (Modifier.isFinal(field.getModifiers()))
							continue;

						field.setAccessible(true);

						Object val = null;
						Field setField = null;
						ConverMapper mapper = field.getAnnotation(ConverMapper.class);
						Precision precision = field.getAnnotation(Precision.class);
						String targetFielde = null;
						if (mapper != null) {
							String converClassName = converClass.getName();
							if (mapper.targetClass().length == 0) {
								targetFielde = mapper.targetFielde()[0];
							} else {
								for (int i = 0; i < mapper.targetClass().length; i++) {
									String mapperClass = mapper.targetClass()[i];

									if (mapperClass.equals(converClassName)) {
										targetFielde = mapper.targetFielde()[i];
										break;
									}
								}
							}
						}

						String fieldName = null;
						if (targetFielde != null && !targetFielde.isEmpty()) {
							fieldName = targetFielde;
						} else {
							fieldName = field.getName();
						}

						if (converType == ConverType.SOURCE) {
							val = field.get(source);

							setField = ReflectionUtils.getDeclaredField(converClass, fieldName);

							if (setField != null)
								setField.setAccessible(true);
						} else if (converType == ConverType.TARGET) {

							Field getField = ReflectionUtils.getDeclaredField(converClass, fieldName);

							if (getField != null) {
								getField.setAccessible(true);
								val = getField.get(source);
							}

							setField = field;
						}

						enumDescConver(source, target, field);

						if (setField == null)
							continue;

						if (customConver != null)
							val = customConver.handler(val, setField);

						if (val == null) {
							DefaultVal defaultVal = field.getAnnotation(DefaultVal.class);
							if (defaultVal != null)
								val = defaultVal.val();
							else
								continue;
						} else if (precision != null) {
							int movePoint = precision.movePoint();
							int scale = precision.scale();
							RoundingMode roundingMode = precision.roundingMode();

							BigDecimal bigDecimal = new BigDecimal(val.toString());
							bigDecimal = bigDecimal.movePointRight(movePoint).setScale(scale, roundingMode);

							if (setField.getType().equals(Short.class)) {
								val = bigDecimal.shortValue();
							} else if (setField.getType().equals(Integer.class)) {
								val = bigDecimal.intValue();
							} else if (setField.getType().equals(Long.class)) {
								val = bigDecimal.longValue();
							} else if (setField.getType().equals(Float.class)) {
								val = bigDecimal.floatValue();
							} else if (setField.getType().equals(Double.class)) {
								val = bigDecimal.doubleValue();
							} else if (setField.getType().equals(String.class)) {
								val = bigDecimal.toString();
							} else {
								val = bigDecimal;
							}
						}

						// 类型转换
						if (Collection.class.isAssignableFrom(setField.getType())) {// 集合转换
							Type genericType = ((ParameterizedType) setField.getGenericType()).getActualTypeArguments()[0];
							if (genericType instanceof WildcardType) {
								WildcardType wildcardType = (WildcardType) genericType;
								Type[] bounds = wildcardType.getLowerBounds();
								if (bounds.length == 0) {
									bounds = wildcardType.getUpperBounds();
								}
								genericType = bounds[0];
							}
							Class setFieldGenericClass = (Class) genericType;
							if (Collection.class.isAssignableFrom(val.getClass())) {
								Collection values = ((Collection) val);
								Collection setFieldCollection = null;

								if (Set.class.isAssignableFrom(setField.getType()))
									setFieldCollection = new HashSet<>();
								else if (List.class.isAssignableFrom(setField.getType()))
									setFieldCollection = new ArrayList<>();

								for (Object obj : values) {
									if (obj == null)
										continue;
									if (setFieldGenericClass.equals(String.class)) {
										obj = obj.toString();
									} else if (setFieldGenericClass.equals(Short.class)) {
										obj = Short.parseShort(obj.toString());
									} else if (setFieldGenericClass.equals(Integer.class)) {
										obj = Integer.parseInt(obj.toString());
									} else if (setFieldGenericClass.equals(Long.class)) {
										obj = Long.parseLong(obj.toString());
									} else if (setFieldGenericClass.equals(Float.class)) {
										obj = Float.parseFloat(obj.toString());
									} else if (setFieldGenericClass.equals(Double.class)) {
										obj = Double.parseDouble(obj.toString());
									} else if (setFieldGenericClass.isEnum()) {
										if (obj.getClass().equals(String.class)) {
											obj = Enum.valueOf(setFieldGenericClass, obj.toString());
										}
									} else if (!setFieldGenericClass.equals(obj.getClass())) {// 复合对象转换
										obj = conver(obj, setFieldGenericClass, converType);
									}
									setFieldCollection.add(obj);
								}
								if (!setFieldCollection.isEmpty())
									val = setFieldCollection;
							} else if (val.getClass().equals(String.class)) {
								val = JSON.parseArray(val.toString(), setFieldGenericClass);
							}
						} else if (Map.class.isAssignableFrom(setField.getType()) && Map.class.isAssignableFrom(val.getClass())) {
							// 不处理
						} else if (!setField.getType().equals(val.getClass())) {
							if (setField.getType().equals(Date.class)) {// 日期转换
								if (val.getClass().equals(Long.class))
									val = new Date((Long) val);
								else if (val.getClass().equals(String.class))
									val = DateUtils.convertDateString(val.toString());
							} else if (setField.getType().equals(Long.class)) {
								if (val.getClass().equals(Date.class))// 日期转换
									val = ((Date) val).getTime();
								else if (val.getClass().equals(String.class)) {
									if (DateUtils.validateLongDateFormat(val.toString()) || DateUtils.validateUnsignedDateFormat(val.toString())
											|| DateUtils.validateShortDateFormat(val.toString()))// 日期转换
										val = DateUtils.convertDateStringToMillisecond(val.toString());
									else
										val = Long.parseLong(val.toString());
								} else if (val.getClass().equals(Integer.class)) {
									val = ((Integer) val).longValue();
								}
							} else if (setField.getType().equals(String.class)) {
								if (val.getClass().equals(Date.class))// 日期转换
									val = DateUtils.convertToLongDateString((Date) val);
								else if (!val.getClass().isPrimitive())
									val = JSON.toJSONString(val);
								else
									val = val.toString();
							} else if (setField.getType().equals(Integer.class)) {
								if (val.getClass().equals(String.class)) {
									val = Integer.parseInt(val.toString());
								} else if (val.getClass().equals(Long.class)) {
									val = ((Long) val).intValue();
								} else if (val.getClass().equals(Byte.class)) {
									val = ((Byte) val).intValue();
								}

							} else if (setField.getType().equals(Double.class)) {
								if (val.getClass().equals(String.class)) {
									val = Double.parseDouble(val.toString());
								}
							} else if (setField.getType().equals(Boolean.class)) {
								if (val.getClass().equals(String.class)) {
									val = Boolean.parseBoolean(val.toString());
								}
							} else if (setField.getType().equals(Float.class)) {
								if (val.getClass().equals(String.class)) {
									val = Float.parseFloat(val.toString());
								}
							} else if (setField.getType().equals(Short.class)) {
								if (val.getClass().equals(String.class)) {
									val = Short.parseShort(val.toString());
								}
							} else if (setField.getType().equals(Byte.class)) {
								if (val.getClass().equals(String.class)) {
									val = Byte.parseByte(val.toString());
								} else if (val.getClass().equals(Integer.class)) {
									val = ((Integer) val).byteValue();
								}
							} else if (setField.getType().isEnum()) {
								if (val.getClass().equals(String.class)) {
									val = Enum.valueOf((Class) setField.getType(), val.toString());
								}
							} else if (setField.getType().equals(BigDecimal.class)) {
								val = new BigDecimal(val.toString());
							} else if (!setField.getType().isPrimitive()) {// 复合对象转换
								if (val.getClass().equals(String.class))
									val = JSON.parseObject(val.toString(), setField.getType());
								else
									val = conver(val, setField.getType(), converType);
							}
						}

						setField.set(target, val);

					}
				} catch (Exception ex) {
					logger.error("Entity conver error, source={}, target={}, converType={}, loopClass={}", JSON.toJSONString(source), JSON.toJSONString(target), converType,
							loopClass, ex);
				}
			}

			return target;
		} catch (Exception ex) {
			logger.error("Entity conver error, source={}, target={}, converType={}", JSON.toJSONString(source), JSON.toJSONString(target), converType, ex);
		}
		return null;
	}

	/**
	 * 枚举描述字段转换
	 */
	private static void enumDescConver(Object source, Object target, Field field) {
		// 枚举描述字段转换
		String descFielde = null;
		Class<? extends EnumInterface> enumClass = null;
		try {
			EnumDesc enumDesc = field.getAnnotation(EnumDesc.class);
			if (enumDesc == null)
				return;

			descFielde = enumDesc.descFielde();
			if (descFielde == null || descFielde.isEmpty())
				descFielde = field.getName() + "Desc";

			enumClass = enumDesc.enumClass();

			Field setField = ReflectionUtils.getDeclaredField(target.getClass(), descFielde);

			if (setField == null)
				return;

			Object enumVal = field.get(source);
			if (enumVal == null)
				return;

			String desc = EnumUtils.getByCode(enumClass, (Integer) enumVal).getDesc();

			setField.setAccessible(true);
			setField.set(target, desc);
		} catch (Exception e) {
			logger.error("枚举描述字段转换失败, source={}, target={}, field={}, descFielde={}, enumClass={}", source, target, field, descFielde, enumClass, e);
		}
	}

	/**
	 * 自定义类型转换接口
	 * 
	 * @author 高总辉
	 */
	public interface CustomConver {
		public Object handler(Object val, Field setField);
	}
	
	/**
	 * 对象深度转换（相同名称的字段）
	 * 遍历目标类所有属性，从源对象获取相同属性名称的属性值，并写入目标对象
	 * @param sourceObj
	 * @param targetClass
	 * @param outerObj 为外层对象
	 * @param <E>
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws NoSuchMethodException
	 * @throws InvocationTargetException
	 */
	public static <E> E deepConvert(Object sourceObj, Class<E> targetClass, Object outerObj) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
		Class<?> sourceClass = sourceObj.getClass();
		Constructor<?>[] constructors = targetClass.getConstructors();
		Constructor<?> constructor = null;
		if (constructors != null && constructors.length > 0) {
			constructor = constructors[0];
		}
		constructor.setAccessible(true);
		Object targetObj;
		if (outerObj == null) {
			targetObj = constructor.newInstance();
		} else {
			targetObj = constructor.newInstance(outerObj);
		}
		Field[] fields = targetClass.getDeclaredFields();
		for (Field field :
				fields) {
			field.setAccessible(true);
			Class<?> fieldType = field.getType();
			if (Modifier.isFinal(field.getModifiers())
						|| Modifier.isStatic(field.getModifiers())
						|| Iterable.class.isAssignableFrom(fieldType)
					) {
				// final 和 static 修饰的属性跳过，集合类型的对象跳过
				continue;
			}
			if (fieldType.equals(String.class)
						|| fieldType.equals(Short.class)
						|| fieldType.equals(Integer.class)
						|| fieldType.equals(Long.class)
						|| fieldType.equals(Float.class)
						|| fieldType.equals(Date.class)
						|| fieldType.equals(Double.class)
					) {// 最终对象
				// 获取源对象的get方法
				Method getMethod = sourceClass.getDeclaredMethod("get" + StringUtils.indexToUpperCase(field.getName()));
				// 从源对象获取属性值，通过set方法写入目标对象
				try {
					Object sourceValue = getMethod.invoke(sourceObj);
					if (sourceValue != null) {
						field.set(targetObj, sourceValue);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {// 子对象
				field.set(targetObj, deepConvert(sourceObj, field.getType(), targetObj));
			}
		}
		return (E) targetObj;
	}
	
}
